package com.singletonapps.evory.service.impl;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.singletonapps.evory.dao.CourseDao;
import com.singletonapps.evory.dao.CourseTemaDao;
import com.singletonapps.evory.dto.CourseDto;
import com.singletonapps.evory.dto.ResponseDto;
import com.singletonapps.evory.entities.Course;
import com.singletonapps.evory.entities.CourseTema;
import com.singletonapps.evory.entities.CourseVideo;
import com.singletonapps.evory.entities.Material;
import com.singletonapps.evory.exception.CreateCourseException;
import com.singletonapps.evory.exception.GuardaArchivoServerException;
import com.singletonapps.evory.service.AdminService;

@Service
public class AdminServiceImpl implements AdminService {
	
	private static final Logger LOGGER = LogManager.getLogger(AdminServiceImpl.class.getName());
	
	@Autowired
	private CourseDao cursoDao;
	@Autowired
	private CourseTemaDao cursoTemaDao;
	
	@Override
	@Transactional(rollbackFor = {CreateCourseException.class, GuardaArchivoServerException.class})
	public ResponseDto createCourse(CourseDto curso, MultipartFile imagen,
			MultipartFile[] materiales, MultipartFile[] videos) throws CreateCourseException, GuardaArchivoServerException {
		
		ResponseDto respuesta = new ResponseDto();
		
		try{
			this.guardaArchivosEnServidor(curso, imagen, materiales, videos);
		} catch (GuardaArchivoServerException gase){
			LOGGER.error("Error subiendo los archivos al Serividor", gase);
			throw new GuardaArchivoServerException("Error subiendo los archivos al Serividor", gase);
		}
		
		try {
			List<CourseTema> temas = new ArrayList<CourseTema>();
			List<Material> materialess = new ArrayList<Material>();
			List<CourseVideo> videoss = new ArrayList<CourseVideo>();
			
			Course c = curso.toEntity();
			
			for (int i = 0; i < curso.getTemas().size(); i++) {
				CourseTema t = new CourseTema();
				t.setNombreTema(curso.getTemas().get(i));
				t.setDescTema(curso.getTemasDesc().get(i));
				t.setCurso(c);
				t.setDateCreated(new Date());
				t.setDateUpdated(new Date());
				t.setVersion(1);
				temas.add(t);
			}
			
			for (int i = 0; i < curso.getMateriales().size(); i++) {
				Material m = new Material();
				m.setCurso(c);
				m.setNombre(curso.getMateriales().get(i));
				m.setDescripcion(curso.getMaterialesDesc().get(i));
				m.setMaterialPath(curso.getMaterialesPaths().get(i));
				m.setDateCreated(new Date());
				m.setDateUpdated(new Date());
				m.setVersion(1);
				
				materialess.add(m);
			}
			
			for (int i = 0; i < curso.getVideos().size(); i++) {
				CourseVideo v = new CourseVideo();
				v.setCursoVideo(c);
				v.setNombre(curso.getVideos().get(i));
				v.setDescripcion(curso.getVideosDesc().get(i));
				v.setVideoPath(curso.getVideosPaths().get(i));
				v.setDateCreated(new Date());
				v.setDateUpdated(new Date());
				v.setVersion(1);
				
				videoss.add(v);
			}
			
			c.setTemasCurso(temas);
			c.setMaterialesCurso(materialess);
			c.setVideosCurso(videoss);
			
			c.setCourseThemes("temas");
			c.setDateCreated(new Date());
			c.setDateUpdated(new Date());
			c.setVersion(1);
			
			cursoDao.create(c);
			
		} catch (Exception e) {
			LOGGER.error("Error Creando el curso en la BD", e);
			throw new CreateCourseException("Error creando el curso", e);
		}
		
		respuesta.setMessage("Proceso OK");
		
		return respuesta;

	}
	
	/**
	 * 
	 * @param curso
	 * @param imagen
	 * @param materiales
	 * @param videos
	 * @throws GuardaArchivoServerException
	 */
	public void guardaArchivosEnServidor(CourseDto curso, MultipartFile imagen,
			MultipartFile[] materiales, MultipartFile[] videos) throws GuardaArchivoServerException{
		
		String rootPath = System.getProperty("catalina.home") + "/eclipseApps/evory-eLearning/resources/videos";//"/home/evory";
		
		/* Se alamcena la imagen del curso*/
		if(!imagen.isEmpty()){
			try {
				
				byte[] bytesImagenCurso = imagen.getBytes();
				
				
				File dir = new File(rootPath + File.separator + "imagenCursos");
				if (!dir.exists()){
                    dir.mkdirs();
				}
				
				File serverFile = new File(dir.getAbsolutePath() + File.separator + imagen.getOriginalFilename());
				BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(serverFile));
				
				stream.write(bytesImagenCurso);
                stream.close();
                
                
                LOGGER.info("Server File Location="
                        + serverFile.getAbsolutePath());
                
                curso.setCourseImagePath("/evory/resources/videos/"+imagen.getOriginalFilename());
                
			} catch (IOException e) {
				LOGGER.error("Error subiendo la imagen del curso", e);
				throw new GuardaArchivoServerException("Error subiendo la imagen del curso", e);
			}
		}
		
		/* Se almacenan los materiales del curso*/
		if(materiales.length > 0){
			try {
				
				File dir = new File(rootPath + File.separator + "materialCursos");
				if (!dir.exists()){
                    dir.mkdirs();
				}
				curso.setMaterialesPaths(new ArrayList<String>());
				
				for (int i = 0; i < materiales.length; i++) {
					
					byte[] bytesMateriale = materiales[i].getBytes();
					File serverFile = new File(dir.getAbsolutePath() + File.separator + materiales[i].getOriginalFilename());
					BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(serverFile));
					
					curso.getMaterialesPaths().add(serverFile.getCanonicalPath());
					stream.write(bytesMateriale);
	                stream.close();
				}
                
			} catch (IOException e) {
				LOGGER.error("Error subiendo Material", e);
				throw new GuardaArchivoServerException("Error subiendo el material del curso", e);
			}
		}
		
		/* Se alamcenan los videos del curso */
		if(videos.length > 0){
			try {
				
				File dir = new File(rootPath + File.separator + "videosCursos");
				if (!dir.exists()){
                    dir.mkdirs();
				}
				
				curso.setVideosPaths(new ArrayList<String>());
				
				for (int i = 0; i < videos.length; i++) {
					
					byte[] bytesVideos = videos[i].getBytes();
					File serverFile = new File(dir.getAbsolutePath() + File.separator + videos[i].getOriginalFilename());
					BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(serverFile));
					
					curso.getVideosPaths().add(serverFile.getCanonicalPath());
					
					stream.write(bytesVideos);
	                stream.close();
				}
                
			} catch (IOException e) {
				LOGGER.error("Error subiendo Video", e);
				throw new GuardaArchivoServerException("Error subiendo los videos del curso", e);
			}
		}
	}
	
	@Override
	@Transactional
	public List<CourseDto> cargaTodosLosCursos(){
		
		List<CourseDto> cursosDtoList = new ArrayList<CourseDto>();
		
		try {
			List<Course> cursos = cursoDao.findAll();
			
			
			for (Course curso : cursos) {
				cursosDtoList.add(curso.toDto());
			}
			
		} catch (Exception e) {
			LOGGER.error("Error cargando los Cursos", e);
		}
		
		return cursosDtoList;
	}

	@Override
	public CourseDto cargarCursoById(Long id) {
		// TODO Auto-generated method stub
		return null;
	}

}
